<?php
/**
 * 模型类文件
 * @abstract 一表一模型，一表一对象，操作无非增删改查。
 * @author 暮雨秋晨
 * @copyright 2014
 */

require_once 'M/Database.php';
require_once 'M/ModelException.php';

class Model
{
    private static $DBH = null; //存储数据库对象
    private static $tables = array(); //存储数据表
    private $table; //存储表名称
    private $sql = ''; //存储连贯操作生成的SQL
    private $FetchMode = PDO::FETCH_ASSOC; //设置连贯操作获取数据使用的返回类型

    public function __construct($table = '')
    {
        if (!self::$DBH) {
            throw new ModelException('Model of uninitialized, please use the static method <b>init</b> to initialize.',
                2);
        }
        $table = trim($table);
        if (!empty($table)) {
            $table = strtolower($table);
            if (empty(self::$tables)) {
                $tables = self::$DBH->getAllRecord('show TABLES', PDO::FETCH_NUM);
                $tables_tmp = array();
                foreach ($tables as $k => $v) {
                    $tables_tmp[] = $v[0];
                }
                $tables = $tables_tmp;
                self::$tables = $tables;
            }
            if (empty(self::$tables) || !in_array($table, self::$tables)) {
                throw new ModelException('The data table "<b>' . $table .
                    '</b>" does not exist.', 2);
            }
            $this->table = $table;
            return true;
        } else {
            throw new ModelException('Initialization failure model, parameters can not be empty.',
                1);
        }
    }

    public static function init($db_type, $db_host, $db_user, $db_pass, $db_name, $db_charset =
        'utf8', $db_pconnect = true)
    {
        $db = new Database($db_type, $db_host, $db_user, $db_pass, $db_name, $db_charset,
            $db_pconnect);
        if (is_object($db)) {
            self::$DBH = $db;
            return true;
        } else {
            return false;
        }
    }

    /**
     * 统一开放SQL执行接口
     */
    public function query($sql)
    {
        return self::$DBH->query($sql);
    }
    public function exec($sql)
    {
        return self::$DBH->exec($sql);
    }

    /**
     * @abstract 增
     * @param array $key_val 插入的数据按 "字段名"=>"值" 的形式组合数组
     */
    public function insert($key_val = array())
    {
        return self::$DBH->insert($this->table, $key_val);
    }

    /**
     * @abstract 删
     * @param array $key_val 删除数据所需的条件，按 "字段名"=>"值" 的形式组合数组
     */
    public function delete($key_val = array())
    {
        return self::$DBH->delete($this->table, $key_val);
    }

    /**
     * @abstract 改
     * @param array $key_val 新的数据按 "字段名"=>"值" 的形式组合数组
     * @param array $conditions 更新数据需要的条件，按 "字段名"=>"值" 的形式组合数组
     */
    public function update($key_val = array(), $conditions = array())
    {
        return self::$DBH->update($this->table, $key_val, $conditions);
    }

    /**
     * @abstract 查单条
     */
    public function fetch($fields = '', $conditions = array(), $mode = PDO::
        FETCH_ASSOC)
    {
        if (!$this->sql) {
            if (empty($fields)) {
                $fields = '*'; //如果目标字段为空，默认获取全部字段
            }
            if (!empty($conditions)) {
                $condition_tmp = array();
                foreach ($conditions as $k => $v) {
                    $condition_tmp[] = "`{$k}`='{$v}'";
                }
                $condition_tmp = ' where ' . implode(' and ', $condition_tmp);
            } else {
                $condition_tmp = '';
            }

            $sql = "select {$fields} from " . $this->table . $condition_tmp;
            return self::$DBH->getOneRecord($sql, $mode);
        } else {
            $sql = $this->sql;
            $this->sql = '';
            return self::$DBH->getOneRecord($sql, $this->FetchMode);
        }

    }

    /**
     * @abstract 查全部，多维数组
     */
    public function fetchAll($fields = '', $conditions = array(), $mode = PDO::
        FETCH_ASSOC)
    {
        if (!$this->sql) {
            if (empty($fields)) {
                $fields = '*'; //如果目标字段为空，默认获取全部字段
            }
            if (!empty($conditions)) {
                $condition_tmp = array();
                foreach ($conditions as $k => $v) {
                    $condition_tmp[] = "{$k}='{$v}'";
                }
                $condition_tmp = ' where ' . implode(' and ', $condition_tmp);
            } else {
                $condition_tmp = '';
            }

            $sql = "select {$fields} from " . $this->table . $condition_tmp;
            return self::$DBH->getAllRecord($sql, $mode);
        } else {
            $sql = $this->sql;
            $this->sql = '';
            return self::$DBH->getAllRecord($sql, $this->FetchMode);
        }
    }

    public function getInsertID()
    {
        return self::$DBH->getInsertID();
    }

    public function count($cond = '')
    {
        if (is_array($cond)) {
            $condtmp = array();
            foreach ($cond as $k => $v) {
                $condtmp[] = "{$k}='{$v}'";
            }
            $cond = ' where ' . implode(',', $condtmp);
        } else {
            $cond = ' ' . $cond;
        }
        $sql = "select * from " . $this->table . $cond;
        return self::$DBH->query($sql)->rowCount();
    }

    /**
     * 连贯操作的各种坑爹东西
     * select * from user where id<'12' order by id desc limit 0,10
     */
    public function select($fields)
    {
        $fields = trim($fields);
        $this->sql = 'select ' . $fields . ' from ' . $this->table;
        return $this;
    }
    public function where($cond)
    {
        $cond = trim($cond);
        $this->sql .= ' where ' . $cond;
        return $this;
    }
    public function order($field, $isASC = true)
    {
        $field = trim($field);
        $sort = $isASC ? 'ASC' : 'DESC';
        $this->sql .= ' order by ' . $field . ' ' . $sort;
        return $this;
    }
    public function limit($start, $num = '')
    {
        $start = $start + 0;
        if (!empty($num)) {
            $num = $num + 0;
            $this->sql .= ' limit ' . $start . ',' . $num;
        } else {
            $this->sql .= ' limit ' . $start;
        }
        return $this;
    }
    public function mode($mode = PDO::FETCH_ASSOC)
    {
        $this->FetchMode = $mode;
        return $this;
    }

    /**
     * 扩展功能
     */
    public function addByAttr($field, $cond = array(), $num = 1)
    {
        $res = $this->fetch($field, $cond);
        if ($this->update(array($field => $res[$field] + $num), $cond)) {
            return $res[$field] + $num;
        } else {
            return false;
        }
    }

}


?>